﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Solidi;

namespace Solidi
{
	/// <remarks>
	/// Thread-safe
	/// </remarks>
	public sealed class DependencyRegistry : IDependencyRegistry
	{
		private ConcurrentDictionary<IDependencyKey, ICollection<IDependency>> _dependencies = new ConcurrentDictionary<IDependencyKey, ICollection<IDependency>>(DependencyKeyEqualityComparer.Default);

		public void Add(IEnumerable<IDependency> dependencies)
		{
            if (dependencies == null)
            {
                throw new ArgumentNullException("dependencies");
            }

			foreach (IDependency dependency in dependencies)
			{
				IDependencyKey key = dependency.Key;

				ICollection<IDependency> list = _dependencies.GetOrAdd(key, (k) => new List<IDependency>());

				lock (list)
				{
					list.Add(dependency);
				}
			}
		}

		public IEnumerable<IDependency> Find(IDependencyKey key, Func<IEnumerable<IDependency>> dependencyFactory)
		{
			if (dependencyFactory != null)
			{
				ICollection<IDependency> list = _dependencies.GetOrAdd(key, (k) => new List<IDependency>(dependencyFactory()));

				lock (list)
				{
					return list.ToArray();
				}
			}
			else
			{
				ICollection<IDependency> list;

				if (_dependencies.TryGetValue(key, out list))
				{
					lock (list)
					{
						return list.ToArray();
					}
				}
			}

			return Enumerable.Empty<IDependency>();
		}
	}
}
